<!doctype html>
<script src = "/resources/testharness.js"></script>
<script src = "/resources/testharnessreport.js"></script>
<script>
// This test verifies that chains of AbortSignal objects do not lose abort
// events due to collection of objects in the middle of the chain. It uses
// Request objects to perform the chaining, as they are currently the only place
// that the https://dom.spec.whatwg.org/#abortsignal-follow operation is used in
// Blink.
//
// This test is Blink-specific because it requires access to garbage collection.
promise_test(async () => {
  assert_not_equals(typeof GCController, undefined,
         'this test requires garbage collection to be exposed');
  // |controller| will have a strong reference to controller.signal.
  const controller = new AbortController();
  // |controller.signal| will hold a weak reference to |signal|.
  let signal = new Request('/', { signal: controller.signal }).signal;
  // |signal| will hold a weak reference to |request.signal|.
  const request = new Request('/', { signal: signal });

  // Allow |signal| to be collected.
  signal = undefined;

  // Experimantely two collections is the right number for collection to
  // reliably happen. If this test starts to flake, try increasing the number.
  for (let i = 0; i < 2; ++i) {
    GCController.collect();
    // Allow the Oilpan GC to run with an empty stack.
    await new Promise(resolve => setTimeout(resolve, 0));
  }

  // Abort should still abort the request.
  controller.abort();
  assert_true(request.signal.aborted, 'aborted should be true');
}, 'aborts should not be lost due to garbage collection');
</script>
